package com.bsoft.core.serialization;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

/**
 * kryo是高性能，针对java的序列化框架，依赖底层ASM库用于字节码生成，因此有比较好的运行速度。
 * Kryo的目标就是提供一个序列化速度快、结果体积小、API简单易用的序列化框架。
 * Kryo支持自动深/浅拷贝，它是直接通过对象->对象的深度拷贝，而不是对象->字节->对象的过程。
 *
 *
 *  kryo常见坑：
 *  1、低版本对map对象支持较弱
 *  2、低版本和高版本兼容较弱（尤其在有map的情况下）TaggedFieldSerializer，CompatibleFieldSerializer
 *  3、使用高版本asm版本与业务本身依赖版本冲突（maven kryo -> kryo-tagded）
 */
public class KryoSerialization implements Serialization {

    /**
     * kryo本身线程不安全，需要线程私有来解决线程安全问题（kryo提供了KryoPool）
     */
    private static final ThreadLocal<Kryo> kryoLocal = ThreadLocal.withInitial(() -> {
        Kryo kryo = new Kryo();
        // 不需要提前预注册类
        kryo.setRegistrationRequired(false);
        // 优化
        kryo.setReferences(false);// 关闭循环依赖
        return kryo;
    });

    @Override
    public <T> byte[] serialize(T obj) {
        Output output = new Output(1024);
        kryoLocal.get().writeClassAndObject(output, obj);
        output.flush();
        return output.toBytes();
    }

    @Override
    public <T> T deserialize(byte[] data, Class<T> clz) {
        Input input = new Input(data);
        Object ob = kryoLocal.get().readClassAndObject(input);
        return (T) ob;
    }
}
